from PySide2.QtWidgets import QTreeWidgetItem,QMessageBox
from PySide2.QtCore import Qt,QSize
from PySide2.QtGui import QDragEnterEvent, QDropEvent,QIcon,QBrush,QColor

from ui import Ui_MainWidget
import os
from PIL import Image
from datetime import datetime
from ElTitleBar import ElTitleBar
from ElWindow import ElWindow
from TreeWidget import TreeWidget
from source import ImageFix
from source.Log import Log
import sys
import re

import enum
# 边缘类型枚举
class LabelColor(enum.Flag):
    Red: int = 0  # 红色
    Yellow: int = 1  # 黄色
    White: int = 2  # 白色
 
 

class Widget(ElWindow,Ui_MainWidget):

    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.resize(QSize(400,580))
        self.setMinimumSize(400,580)
        self.setWindowIcon(QIcon(':/icons/logo.png'))

        self._initDictorySetting()

        self._initOtherUi()
        self.log = Log()



        self.setAcceptDrops(True)

        self.radioButton_scall.setChecked(True)
        
        # 进度条
        self.progressBar.setValue(0)
        # 提示label
        self.setLabelTipsText('没事看下帮助,点击右上方的 ? 号')
        # 槽函数
        self.pushButton_check.clicked.connect(self.slot_pushbuttonCheckClicked)
        self.pushButton_fixPixel.clicked.connect(self.slot_pushbuttonFixPixelClicked)
        self.pushButton_openSaveDirectory.clicked.connect(self.slot_pushButton_openSaveDirectory)
        self.lineEdit_imageSavePath.textChanged.connect(self.slot_lineEdit_imageSavePath)
        self.checkBox_topWindow.stateChanged.connect(self.slot_checkBox_topWindow)


    def _initOtherUi(self):
        self.titlebar = ElTitleBar(self,'ImageFix 1.0   by:冰叶伤痕')
        self.titlebar.setStyle(u"background-color: rgb(80, 80, 80);\n"
        "color: rgb(160, 160, 160);\n"
        "font: 75 14pt \"\u5fae\u8f6f\u96c5\u9ed1\";")
        self.treeWidget = TreeWidget(self)
        self.verticalLayout_fileList.addWidget(self.treeWidget)


    def _initDictorySetting(self):
        # 获取当前执行文件的路径
        path = os.path.abspath(sys.executable)

        # 执行文件目录
        self.exetDirectory = os.path.dirname(path)
        
        # 获取文件名
        filename = os.path.basename(path)
        
        # 判断执行文件名是否以 'python.exe' 结尾
        if filename == 'python.exe':
            # 获取当前文件的目录
            self.exetDirectory = os.path.dirname(os.path.abspath(__file__))

        # 图像修复目录
        imageSavePath = self.exetDirectory + '\\Images'
        # 检查目录是否存在
        if not os.path.exists(imageSavePath):
            # 创建目录
            os.makedirs(imageSavePath)
        self.lineEdit_imageSavePath.setText(imageSavePath)
        self.slot_lineEdit_imageSavePath()


    # def resizeEvent(self, event):
    #     super().resizeEvent(event)



    def dragEnterEvent(self, event: QDragEnterEvent):
            # 检查拖入的事件是否包含URLs
            if event.mimeData().hasUrls():
                # 如果包含URLs，则接受建议的动作
                event.acceptProposedAction()


    def dropEvent(self, event: QDropEvent):
        # 获取拖放事件中的URLs
        urls = event.mimeData().urls()
        # 遍历URLs
        for url in urls:
            # 判断URL是否为本地文件
            if url.isLocalFile():
                # 获取本地文件路径
                local_file = url.toLocalFile()

                # 判断本地文件是否为文件
                if os.path.isfile(local_file):
                    # 获取文件所在目录
                    self.loadDirectory = os.path.dirname(local_file)
                # 判断本地文件是否为目录
                elif os.path.isdir(local_file):
                    self.loadDirectory = local_file
                
                if self.loadDirectory:
                    # 显示当前加载目录
                    self.loadDirectory = os.path.normpath(self.loadDirectory).replace('/', '\\')
                    self.label_directoyPath.setText(self.loadDirectory)


    def setLabelTipsText(self,text:str,color:LabelColor = LabelColor.White):
        self.label_tip.setText(text)
        
        if color == LabelColor.White:
            self.label_tip.setStyleSheet(u"background-color: rgb(141, 141, 141);\n"
    "font: 12pt \"\u5fae\u8f6f\u96c5\u9ed1\";\n"
    "color: rgb(210, 210, 210);")
        
        if color == LabelColor.Red:
            self.label_tip.setStyleSheet(u"background-color: rgb(141, 141, 141);\n"
    "font: 12pt \"\u5fae\u8f6f\u96c5\u9ed1\";\n"
    "color: rgb(255, 0, 127);")
        
        if color == LabelColor.Yellow:
            self.label_tip.setStyleSheet(u"background-color: rgb(141, 141, 141);\n"
    "font: 12pt \"\u5fae\u8f6f\u96c5\u9ed1\";\n"
    "color: #FAD714;")


    def findImageFiles(self):
        self.imgFiles = []
        if not hasattr(self,'loadDirectory'):
            return self.imgFiles
        
        nowtime = self.getTimeFormatted()
        self.log.append(f'\n\n#查找图片文件:\t{nowtime}')

        extensions = {".jpg", ".jpeg", ".png", ".tga", ".bmp",}

        # 查找子目录图片
        if self.checkBox_childDirectory.isChecked():
            for root, dirs, files in os.walk(self.loadDirectory):
                for file in files:
                    if os.path.splitext(file)[1].lower() in extensions:
                        filePath = os.path.join(root, file)
                        self.imgFiles.append(filePath)
                        self.log.append(filePath)
        else:
            for file in os.listdir(self.loadDirectory):
                if os.path.splitext(file)[1].lower() in extensions:
                    filePath = os.path.join(self.loadDirectory, file)
                    self.imgFiles.append(filePath)
                    self.log.append(filePath)

        return self.imgFiles


    def initTreeWidgetItem(self):
        self.treeWidget.clear()
        # 创建一个 QBrush 实例并设置颜色
        brushRed = QBrush(QColor(255,0,90))
        # 创建一个 QBrush 实例并设置颜色
        brushGreen = QBrush(QColor(135,250,70))

        normalItems = []
        exceptionItems = []
        errorItems = []
        for file in self.normalImageFiles:
            # 获取文件名和后缀名
            baseName = os.path.basename(file)
            item = QTreeWidgetItem([f'{baseName}','正常'])
            normalItems.append(item)
            item.setForeground(1, brushGreen)
            item.setTextAlignment(1,Qt.AlignCenter)
        
        for file in self.exceptionImageFiles:
            baseName = os.path.basename(file)
            item = QTreeWidgetItem([f'{baseName}','异常'])
            exceptionItems.append(item)
            item.setForeground(1, brushRed)
            item.setTextAlignment(1,Qt.AlignCenter)

        for file in self.errorImageFiles:
            baseName = os.path.basename(file)
            item = QTreeWidgetItem([f'{baseName}','图像错误'])
            errorItems.append(item)
            item.setForeground(1, brushRed)
            item.setTextAlignment(1,Qt.AlignCenter)
    
        self.treeWidget.addTopLevelItems(errorItems)
        self.treeWidget.addTopLevelItems(exceptionItems)
        self.treeWidget.addTopLevelItems(normalItems)


    def slot_pushbuttonCheckClicked(self):
        if not hasattr(self,'loadDirectory'):
            self.setLabelTipsText('请拖入文件或文件夹!再点击 检测 按钮!',LabelColor.Red)
            return
        
        files = self.findImageFiles()

        nowtime = self.getTimeFormatted()
        self.normalImageFiles = []
        self.exceptionImageFiles = [] 
        self.errorImageFiles = []
        
        
        self.log.append(f'\n\n#检测:\t{nowtime}')
        # 检测文件
        for file in files:
            try:
                img = Image.open(file)
            except Image.UnidentifiedImageError:
                self.errorImageFiles.append(file)
                self.log.append(f'图像错误\t{file}')
            else:
                width, height = img.size

                # 正常
                if width % 2 ==0 and height % 2 == 0:
                    self.normalImageFiles.append(file)
                    self.log.append(f'图像正常\t像素:宽 {width} 高 {height}\t{file}')
                # 存在奇数宽高
                else:
                    self.exceptionImageFiles.append(file)
                    self.log.append(f'图像异常\t像素:宽 {width} 高 {height}\t{file}')

        self.initTreeWidgetItem()
    

    def slot_lineEdit_imageSavePath(self):
        path =  self.lineEdit_imageSavePath.text()
        # 正则表达式匹配Windows和Linux/Unix路径
        pattern = re.compile(r'^[a-zA-Z]:\\(?:[^\\/:*?"<>|\r\n]+\\)*[^\\/:*?"<>|\r\n]*$|^\/(?:[^\/:.*?"<>|\r\n]+\/)*[^\/:.*?"<>|\r\n]*$')

        if not bool(pattern.match(path)):
            self.setLabelTipsText('存储目录 路径无效!',LabelColor.Yellow)
            self.imageSavePathValid = False
            QMessageBox.about(self,'','路径无效!')
        else:
            self.imageSavePathValid = True


    def slot_checkBox_topWindow(self,state:int):
        if state == Qt.Checked:
            # 设置窗口置顶
            self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
            self.show()
        else:
            # 取消窗口置顶
            self.setWindowFlags(self.windowFlags() & ~Qt.WindowStaysOnTopHint)
            self.show()


    def slot_pushButton_openSaveDirectory(self):
        path = self.lineEdit_imageSavePath.text()
        if os.path.exists(path):
            os.startfile(path)
        else:
            QMessageBox.about(self,'ImageFix','目录不存在!')


    def getTimeFormattedFileName(self):
        now = datetime.now()
        # 格式化为字符串
        formatted_now = now.strftime("%Y-%m-%d_%H-%M-%S")
        return formatted_now
    
    
    def getTimeFormatted(self):
        now = datetime.now()
        # 格式化为字符串
        formatted_now = now.strftime("%Y-%m-%d %H:%M:%S")
        return formatted_now


    def saveImage(self,img:Image.Image,filePath:str):
        # 获取最后一个目录或文件的名称
        directoryName = os.path.basename(self.loadDirectory)
        # 替换前置目录
        saveDirectory = self.lineEdit_imageSavePath.text()

        filePath = filePath.replace(self.loadDirectory,saveDirectory + '\\' + directoryName)
        dictoryPath = os.path.dirname(filePath)
        os.makedirs(dictoryPath,exist_ok=True)
        img.save(filePath)


    def slot_pushbuttonFixPixelClicked(self):
        if not hasattr(self,'exceptionImageFiles'):
            return
        
        count = len(self.exceptionImageFiles)
        if count == 0 :
            self.progressBar.setValue(0)
            return

        # 存储路径无效
        if not self.imageSavePathValid:
            return

        index = 0
        processValue = 0
        nowtime = self.getTimeFormatted()


        if self.radioButton_crop.isChecked():
            self.log.append(f'\n\n#修复图像 模式:裁剪\t{nowtime}')
            for file in self.exceptionImageFiles:
                baseName = os.path.basename(file)
                self.setLabelTipsText(f'正在修复  {baseName}')
                img = ImageFix.cropFix(file)
                self.log.append(f'{file}')
                # 保存修复图像
                self.saveImage(img,file)

                index = index + 1
                if index == count:
                    self.setLabelTipsText('修复完成!')
                processValue = int (index / count * 100)
                self.progressBar.setValue(processValue)

        if self.radioButton_expand.isChecked():
            self.log.append(f'\n\n#修复图像 模式:扩展\t{nowtime}')
            for file in self.exceptionImageFiles:
                baseName = os.path.basename(file)
                self.setLabelTipsText(f'正在修复  {baseName}')
                img = ImageFix.expandFix(file)
                self.log.append(f'{file}')
                # 保存修复图像
                self.saveImage(img,file)
                
                index = index + 1
                if index == count:
                    self.setLabelTipsText('修复完成!')
                processValue = int (index / count * 100)
                self.progressBar.setValue(processValue)

        if self.radioButton_scall.isChecked():
            self.log.append(f'\n\n#修复图像 模式:缩放\t{nowtime}')
            for file in self.exceptionImageFiles:
                baseName = os.path.basename(file)
                self.setLabelTipsText(f'正在修复  {baseName}')
                img = ImageFix.scallFix(file)
                self.log.append(f'{file}')
                # 保存修复图像
                self.saveImage(img,file)
               
                index = index + 1
                if index == count:
                    self.setLabelTipsText('修复完成!')
                processValue = int (index / count * 100)
                self.progressBar.setValue(processValue)